package nl.stroep.classbuilder.cb 
{
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import nl.stroep.classbuilder.cb.interfaces.ICbObject;
	import nl.stroep.classbuilder.cb.interfaces.ICbWrapper;
	import nl.stroep.classbuilder.definitions.Chars;
	import nl.stroep.classbuilder.definitions.ClassMethods;
	import nl.stroep.classbuilder.definitions.Keywords;
	import nl.stroep.classbuilder.utils.ObjectUtil;
	import nl.stroep.classbuilder.utils.XMLUtil;
	
	/**
	 * Method definition
	 * @author Mark Knol - Stroep.nl - 2010 (c)
	 */
	[bindable]
	public class CbMethod extends EventDispatcher implements ICbObject, ICbWrapper, IEventDispatcher
	{
		private var cbObject:CbObject;
		
		private var _name:String;
		private var _type:String;
		private var _accessModifier:String;
		private var _modifier:String;
		private var _defaultValue:String;
		private var _isGetter:Boolean;
		private var _isSetter:Boolean;
		
		public var parameters:Vector.<CbParameter>;
		
		public function CbMethod(name:String, type:String = "void", parameters:Vector.<CbParameter> = null, accessModifier:String = "public", modifier:String = null, defaultValue:String = null, isGetter:Boolean = false, isSetter:Boolean = false ) 
		{
			this._name = name;
			this._type = type;
			this._accessModifier = accessModifier;
			this._modifier = modifier;
			this._defaultValue = defaultValue;
			this._isGetter = isGetter;
			this._isSetter = isSetter;
			
			this.parameters = parameters ? parameters : new Vector.<CbParameter>();
			
			cbObject = new CbObject(ClassMethods.FUNCTION, name);
		}
		
		public function addParameter(cbParameter:CbParameter):void
		{
			parameters.push(cbParameter);
		}
		
		public override function toString():String
		{
			cbObject.name = this._name;
			cbObject.type = this._type; 
			cbObject.parameters = parameters;
			cbObject.accessModifier = this._accessModifier;
			cbObject.modifier = this._modifier;
			cbObject.isGetter = this._isGetter;
			cbObject.isSetter = this._isSetter;
			
			if (!defaultValue)
			{
				cbObject.defaultValue = "{"  + getVariableList() + "// TODO: function " + this._name + "}";
			}
			else
			{
				cbObject.defaultValue = "{" + getVariableList() + ( this._defaultValue ? this._defaultValue : Chars.EMPTY ) + "}";
			}
			
			return cbObject.toString()
		}
		
		public function toXML():XML
		{
			var xml:XML = <method/>;
			
			xml.appendChild( XMLUtil.getNode("name", this._name) );
			xml.appendChild( XMLUtil.getNode("type", this._type) );
			xml.appendChild( XMLUtil.getNode("accessModifier", this._accessModifier) );
			xml.appendChild( XMLUtil.getNode("modifier", this._modifier) );
			xml.appendChild( XMLUtil.getNode("isGetter", this._isGetter) );
			xml.appendChild( XMLUtil.getNode("isSetter", this._isSetter) );
			xml.appendChild( XMLUtil.getNode("defaultValue", this._defaultValue) );
			
			xml.appendChild(<parameters/>);
			
			for (var i:int = 0; i < parameters.length; ++i) 
			{
				xml.parameters.appendChild( parameters[i].toXML() );
			}
			
			return xml;
		}
		
		public static function parseItem(xml:XML):CbMethod
		{
			var func:CbMethod = new CbMethod(
				ObjectUtil.parseString( xml.name.text() ),
				ObjectUtil.parseString( xml.type.text() ),
				CbParameter.parseData( xml.parameters ),
				ObjectUtil.parseString( xml.accessModifier.text() ),
				ObjectUtil.parseString( xml.modifier.text() ),
				ObjectUtil.parseString( xml.defaultValue.text() ),
				ObjectUtil.parseBoolean( xml.isGetter.text() ),
				ObjectUtil.parseBoolean( xml.isSetter.text() )
			)
			
			return func;
		}
		
		public static function parseData(xml:XMLList):Vector.<CbMethod> 
		{
			var retval:Vector.<CbMethod> = new Vector.<CbMethod>();
			
			if (xml.method.length() > 0)
			{
				const total:uint = xml.method.length();
				
				for (var i:int = 0; i < total; ++i) 
				{
					var func:CbMethod = CbMethod.parseItem(xml.method[i]);
					retval.push(func);
				}
			}
			return retval;
		}
		
		private function getVariableList():String
		{
			var retval:String = Chars.EMPTY;
			
			if (parameters && parameters.length > 0)
			{
				const TOTAL:int = parameters.length;
				
				for (var i:uint = 0; i < parameters.length; ++i) 
				{
					var parameter:CbParameter = parameters[i];
					if ((!isGetter || !isSetter) && parameter.addToFunction && parameter.addToClass)
					{
						retval += Keywords.THIS + Chars.DOT + parameter.name + Chars.EQUAL + parameter.name + Chars.SEMICOLON + Chars.NEWLINE;
					}
				}
			}
			return retval;
		}
		
		public function get name():String { return _name; }
		
		public function set name(value:String):void 
		{
			_name = value;
		}
		
		public function get type():String { return _type; }
		
		public function set type(value:String):void 
		{
			_type = value;
		}
		
		public function get accessModifier():String { return _accessModifier; }
		
		public function set accessModifier(value:String):void 
		{
			_accessModifier = value;
		}
		
		public function get modifier():String { return _modifier; }
		
		public function set modifier(value:String):void 
		{
			_modifier = value;
		}
		
		public function get defaultValue():String { return _defaultValue; }
		
		public function set defaultValue(value:String):void 
		{
			_defaultValue = value;
		}
		
		public function get isGetter():Boolean { return _isGetter; }
		
		public function set isGetter(value:Boolean):void 
		{
			_isGetter = value;
		}
		
		public function get isSetter():Boolean { return _isSetter; }
		
		public function set isSetter(value:Boolean):void 
		{
			_isSetter = value;
		}
		
	}

}